#include "../src/parser/sql_parser.h"
#include <stdio.h>
#include <stdlib.h>

static void print_expression(expression_t* expr, int indent);
static void print_statement(statement_t* stmt);

static void print_expression(expression_t* expr, int indent) {
    if (!expr) {
        printf("%*sNULL expression\n", indent, "");
        return;
    }
    
    printf("%*sExpression type: %d\n", indent, "", expr->type);
    
    switch (expr->type) {
        case EXPR_LITERAL:
            printf("%*sLiteral: '%s'\n", indent, "", expr->data.literal.value ? expr->data.literal.value : "NULL");
            break;
        case EXPR_COLUMN:
            printf("%*sColumn: %s.%s\n", indent, "", 
                   expr->data.column.table_name ? expr->data.column.table_name : "",
                   expr->data.column.column_name ? expr->data.column.column_name : "NULL");
            break;
        case EXPR_LIST:
            printf("%*sList with %u items:\n", indent, "", expr->data.list.count);
            for (uint32_t i = 0; i < expr->data.list.count; i++) {
                printf("%*sItem[%u]:\n", indent, "", i);
                print_expression(expr->data.list.expressions[i], indent + 2);
            }
            break;
        case EXPR_BINARY_OP:
            printf("%*sBinary op: %d\n", indent, "", expr->data.binary_op.operator);
            printf("%*sLeft:\n", indent, "");
            print_expression(expr->data.binary_op.left, indent + 2);
            printf("%*sRight:\n", indent, "");
            print_expression(expr->data.binary_op.right, indent + 2);
            break;
        default:
            printf("%*sUnhandled expression type: %d\n", indent, "", expr->type);
            break;
    }
}

static void print_statement(statement_t* stmt) {
    if (!stmt) {
        printf("NULL statement\n");
        return;
    }
    
    printf("Statement type: %d\n", stmt->type);
    
    switch (stmt->type) {
        case STMT_SELECT:
            printf("SELECT List:\n");
            print_expression(stmt->data.select.select_list, 1);
            
            if (stmt->data.select.from_list) {
                printf("FROM:\n");
                table_ref_t* table = stmt->data.select.from_list; 
                bool is_first = true;
                while (table) {
                    if (is_first) {
                        printf("  table: %s\n", table->table_name ? table->table_name : "NULL");
                        if (table->alias) {
                            printf("  alias: %s\n", table->alias);
                        }
                        is_first = false;
                    } else {
                        // This is a joined table
                        const char* join_type_str = "UNKNOWN";
                        if (table->join_type == TOKEN_INNER) {
                            join_type_str = "INNER JOIN";
                        } else if (table->join_type == TOKEN_JOIN) {
                            join_type_str = "JOIN";
                        }
                        
                        printf("  %s: %s\n", join_type_str, table->table_name ? table->table_name : "NULL");
                        if (table->alias) {
                            printf("    alias: %s\n", table->alias);
                        }
                        if (table->join_condition) {
                            printf("    ON condition:\n");
                            print_expression(table->join_condition, 6);
                        }
                    }
                    table = table->next;
                }
            }
            
            if (stmt->data.select.where_clause) {
                printf("WHERE:\n");
                print_expression(stmt->data.select.where_clause, 1);
            }
            
            if (stmt->data.select.order_by) {
                printf("ORDER BY:\n");
                print_expression(stmt->data.select.order_by, 1);
            }
            
            if (stmt->data.select.limit > 0) {
                printf("LIMIT: %u\n", stmt->data.select.limit);
            }
            
            if (stmt->data.select.offset > 0) {
                printf("OFFSET: %u\n", stmt->data.select.offset);
            }
            break;
            
        default:
            printf("Statement details not implemented for this type\n");
            break;
    }
}

static void test_join_queries() {
    printf("=== Testing JOIN Statements ===\n");
    
    const char* test_queries[] = {
        "SELECT u.name, p.title FROM users u INNER JOIN posts p ON u.id = p.user_id",
        "SELECT * FROM orders o JOIN customers c ON o.customer_id = c.id",
        "SELECT u.name, p.title, c.name FROM users u INNER JOIN posts p ON u.id = p.user_id INNER JOIN categories c ON p.category_id = c.id"
    };
    
    for (size_t i = 0; i < sizeof(test_queries) / sizeof(test_queries[0]); i++) {
        printf("\nTest %zu: %s\n", i + 1, test_queries[i]);
        
        parser_t* parser = parser_create(test_queries[i]);
        if (!parser) {
            printf("Failed to create parser\n");
            continue;
        }
        
        statement_t* stmt = parser_parse_statement(parser);
        
        if (parser_has_error(parser)) {
            printf("Parse error: %s\n", parser_get_error(parser));
        } else if (stmt) {
            printf("Parse successful:\n");
            print_statement(stmt);
            statement_destroy(stmt);
        } else {
            printf("No statement parsed\n");
        }
        
        parser_destroy(parser);
    }
}

int main() {
    printf("GuDB JOIN Parser Test\n");
    printf("=====================\n");
    
    test_join_queries();
    
    printf("\n=== Tests Completed ===\n");
    return 0;
}